
package saxon.gui.model;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 *
 * @author lennyn
 */
class ProcessRunner {

	private final static int BUFFER_SIZE = 1024;
	private final ProcessBuilder processBuilder;

	public ProcessRunner(String... args) {
		processBuilder = new ProcessBuilder(args);
	}

	public String run(String input) throws IOException {
		Process process = processBuilder.start();
		int status;
		Reader outReader = new Reader(process.getInputStream());
		Reader errReader = new Reader(process.getErrorStream());
		try {
			outReader.start();
			errReader.start();

			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));

			writer.append(input);
			writer.flush();
			writer.close();

			outReader.join();
			errReader.join();
			status = process.waitFor();
		}
		catch (InterruptedException ex) {
			throw new ProcessRunnerException("Interrupted", ex);
		}
		finally {
			try {
				process.getInputStream().close();
			}
			catch (IOException ex) {}
			try {
				process.getErrorStream().close();
			}
			catch (IOException ex) {}
		}

		if (status == 0 && outReader.isSuccessful())
			return outReader.getData();
		else if (status != 0 && errReader.isSuccessful())
			throw new ProcessRunnerException(errReader.getData());
		else
			throw new ProcessRunnerException("Broken pipe or what...");
	}

	private class Reader extends Thread {

		private final BufferedReader reader;
		private final StringBuilder sb = new StringBuilder();
		private Exception exception = null;

		Reader(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in), BUFFER_SIZE);
		}

		String getData() {
			return sb.toString();
		}

		boolean isSuccessful() {
			return exception == null;
		}

		Exception getException() {
			return exception;
		}

		@Override
		public void run() {
			String line = "";
			try {
				while (!Thread.interrupted() && line != null) {
					line = reader.readLine();
					if (line != null) {
						sb.append(line);
						sb.append("\n");
					}
				}
			}
			catch (IOException ex) {
				exception = ex;
			}
		}
	}
}
